module dice.render.pattern;

import dice.render.canvas;
import dice.render.structs;

/** Implemented by something that will need updating when an associated pattern changes */
interface Updatable
{
	/** Notify this object that it may need updating or redrawing */
	void update ();
}

/** A pattern that can be used to fill or outline shapes
 *
 * TODO: Find a way to use weak references for updatables
 */
class Pattern : Updatable
{
	Updatable[] updatables;
		
	/** Attach an object to this pattern, so if/when the pattern changes, the object can be updated. */
	void attach (Updatable u)
	{
		updatables ~= u;
	}
	
	/** Undoes a corresponding call to attach */
	void detach (Updatable u)
	{
		Updatable[] ups;
		foreach (Updatable i; updatables)
			if (i != u)
				ups ~= i;
		updatables = ups;
	}
	
	/** Notifies all attached objects that the pattern has been modified */
	void update ()
	{
		foreach (Updatable i; updatables)
			i.update();
	}
}

/** A simple gradient pattern */
class Gradient : Pattern
{
	struct Node
	{
		float point;
		Colour colour;
	}
	
	Node[] nodes;
	
	void add (float p, Colour c)
	{
		synchronized (this)
		{
			int pos;
			for (pos = 0; pos < nodes.length && nodes[pos].point < p; pos++) {}
			nodes = nodes[0..pos] ~ Node(p,c) ~ nodes[pos..nodes.length]; 
		}
	}
	
	float x1, y1, x2, y2;
	
	this (float _x1, float _y1, float _x2, float _y2)
	{
		x1 = _x1;
		y1 = _y1;
		x2 = _x2;
		y2 = _y2;
	}
}

/** A pattern that uses data from a pixmap */
class PixmapPattern : Pattern
{
	Pixmap pixmap;
	
	this (Pixmap p)
	{
		pixmap = p;
	}
}
